home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Commun⁄Network / Telnet 2.5.src.ThinkC / source / ftpbin.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-16  |  59.4 KB  |  1,983 lines  |  [TEXT/KAHL]

  1. /*
  2. *  User FTP
  3. *  6/8/87
  4. ****************************************************************************
  5. *                                                                          *
  6. *      by Tim Krauskopf and Swami Natarajan                                *
  7. *                                                                          *
  8. *      National Center for Supercomputing Applications                     *
  9. *      152 Computing Applications Building                                 *
  10. *      605 E. Springfield Ave.                                             *
  11. *      Champaign, IL  61820                                                *
  12. *                                                                          *
  13. *                                                                          *
  14. ****************************************************************************
  15. */
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <ctype.h>
  19. #include <string.h>
  20.  
  21. #include <Controls.h>
  22. #include <Desk.h>
  23. #include <Dialogs.h>
  24. #include <DiskInit.h>
  25. #include <Events.h>
  26. #include <Fcntl.h>
  27. #include <Files.h>
  28. #include <Fonts.h>
  29. #include <Menus.h>
  30. #include <Memory.h>
  31. #include <OSEvents.h>
  32. #include <OSUtils.h>
  33. #include <Packages.h>
  34. #include <Quickdraw.h>
  35. #include <Resources.h>
  36. #include <Script.h>
  37. #include <ToolUtils.h>
  38. #include <Windows.h>
  39.  
  40. #include "wind.h"
  41. #include "configrec.h"
  42. #include "hostform.h"
  43. #include "whatami.h"
  44. #include "VSkeys.h"
  45. #include "prefs.h"
  46. #include "user.h"
  47. #include "util.h"
  48. #include "bkgr.h"
  49. #include "maclook.h"
  50. #include "netevent.h"
  51. #include "vsinterf.h"
  52. #include "menu.h"
  53. #include "rsmac.h"
  54. #include "macbinary.h"
  55. #include "binsubs.h"
  56.  
  57. #include "ftppi.h"        /* list of commands, help strings */
  58.  
  59. #define MACBINARY
  60.  
  61. #define FASCII 0
  62. #define FIMAGE 1    /* This is different than the definition in bkgr.c */
  63. #define FAMODE 0
  64. #define FIMODE 1
  65. #define FMMODE 2    /* Mac Binary, when ready */
  66.  
  67. #define HFTP  21
  68.  
  69. #define FALSE       0
  70. #define TRUE       1
  71. #define SUCCESS       2
  72. #define ERROR      -1
  73. #define NONE      -2
  74. #define ABORT      -3
  75. #define INCOMPLETE -4
  76. #define AMBIGUOUS -5
  77. #define HAVEDATA   4
  78.  
  79. #define BUFFERS 8000    /* size of buffer */
  80. #define PATHLEN 256
  81. #define READSIZE 128    /* how much to read */
  82.  
  83. #define HELPRESID 23229
  84.  
  85. long
  86.     filelen=0,            /* file transfer length */
  87.     start=0L,            /* timing var */
  88.     towrite=0,            /* file transfer pointer */
  89.     translen=0,            /* length of file transfered */
  90.     transtime;
  91.  
  92. int 
  93.     xp=0,                /* general pointer */
  94.     ftpfh,                /* file handle for ftp */
  95.     fcnt = 0,            /* counter for ftpd */
  96.     ftpfilemode=0,        /* file open mode for transfer */
  97.     hash=0,                /* hash mark printing */
  98.     sendport=1,            /* to send ports or not */
  99.     verbose=1,            /* informative messages */
  100.     bell=0,                /* sound bell */
  101.     autologin=1,        /* login on connect */
  102.     prompt=1,            /* check on multiple commands */
  103.     glob=1,                /* expand wildcards */
  104.     slashflip=1,        /* change \ to / */
  105.     fromtty=1;            /* default input from tty */
  106.  
  107. static int ftpdata;
  108.  
  109. #ifdef PC
  110.  
  111. #define RCPSEGSIZE 1024
  112. #define EOLCHAR 10
  113.  
  114. #ifdef MSC
  115. #define O_RAW O_BINARY
  116. #endif
  117.  
  118. #else
  119.  
  120. extern char
  121.     *firstname(),
  122.     *nextname();
  123.  
  124. extern unsigned char SLIP_ip_number[];
  125.  
  126. extern int 
  127.     defaultv,
  128.     ftpenable,
  129.     MacBinary,
  130.     chgdir(),
  131.     ftpdo(),
  132.     netputuev(),
  133.     Sfread(),
  134.     Sfwrite(),
  135.     WindByPort();
  136.  
  137. extern MBFile
  138.     *MBopen();
  139.  
  140. extern void 
  141.     GetFileInfo(),
  142.     setupport();
  143.  
  144. #define RCPSEGSIZE 512
  145. #define O_RAW O_RDONLY
  146. #define EOLCHAR 13
  147. #endif
  148.  
  149. FILE
  150.     *fromfp=NULL;            /* file pointer for input */
  151.  
  152. MBFile
  153.     *ftp_mbfp;
  154.  
  155. FileParam iop;
  156.  
  157. #define captlistsize 2001L
  158. unsigned char 
  159.     *captlist = 0L,
  160.     *newfile = 0L,
  161.     *transfile = 0L,        /* name of file being sent/received */
  162.     *xs = 0L;                /* response string */
  163.  
  164. unsigned int curftpprt = 0;    /* port to use */
  165.  
  166. unsigned char 
  167.     *neterrstring();
  168.  
  169. static char bellchar = { 7 };
  170. static char backspace = { 8 };
  171. static char poundsign = { '#' };
  172.  
  173. char response_data[20][4];            /* BYU 2.4.12 - first 4 characters of each response */
  174. unsigned char response_count[20];    /* BYU 2.4.12 - non-zero indicates waiting for response */
  175.  
  176. extern long JuggTicks;            /* How many ticks to wait when Juggling */
  177. extern int debug,ev,Juggling,scrn;
  178. extern WindRec *screens;
  179. extern char Sptypes[];            /* BYU 2.4.16 - flags for port #'s */
  180.  
  181. /* Beginning of Macintosh Routines created at BYU, 1988 */
  182.  
  183. /************************************************************************/
  184. /* putstring: display string using vt100 emulation routines
  185. /************************************************************************/
  186.  
  187. putstring(ftpscrn,string) int ftpscrn; char *string; {
  188. for (; *string; string++) parse( &screens[ftpscrn],(unsigned char *) string,1);
  189. }
  190.  
  191. nputs(line) char *line; {
  192.   putln(line);
  193. }
  194.  
  195. char *stpblkp(mystring) char *mystring; {
  196. /* Return pointer to first non blank in string */
  197. int mycnt;
  198. char *p;
  199.   mycnt = 0;
  200.   p = mystring;
  201.   while (((*p == ' ') || (*p == '\t')) && (mycnt < 256)) {
  202.     p++;
  203.     mycnt++;
  204.   }
  205.   return(p);
  206. }
  207.  
  208. char *stptok(mystring,myword,mylen,myterms) char *mystring,*myword,*myterms; int mylen; {
  209. /* Return pointer to first non blank in string */
  210. int done,i;
  211. char *p,*q;
  212.  
  213.     p = stpblkp(mystring);            /* skip leading blanks */
  214.     i = 0;
  215.     done = 0;
  216.     while (*(p+i) && (i <= mylen) && (done == 0)) {
  217.       q = myterms;
  218.       while ((*q) && (*q != *(p+i))) q++;
  219.       if (!(*q)) {
  220.         *(myword+i) = *(p+i);
  221.         i++;
  222.       } else done = 1;
  223.     } 
  224.     *(myword+i) = '\0';
  225.     q = p+i;
  226.     return(q);
  227. }
  228.  
  229. int ftpopen(name) char *name; {
  230. int myerr;
  231. short myvrefnum,myrefnum;
  232. char volname[256];
  233.   GetVol(volname,&myvrefnum);
  234.   myerr = FSOpen(name,myvrefnum,&myrefnum);
  235.   return(myrefnum);
  236. }
  237.  
  238. int ftpcreate(name) char *name; {
  239. int myerr;
  240. short myvrefnum,myrefnum;
  241. char volname[256];
  242.   GetVol(volname,&myvrefnum);
  243.   myerr = Create(name,myvrefnum,'????','TEXT');
  244.   myerr = FSOpen(name,myvrefnum,&myrefnum);
  245.   return(myrefnum);
  246. }
  247.  
  248. /* End of Macintosh Routines created at BYU, 1988 */
  249.  
  250. /************************************************************************/
  251. /* ftpgets - read a line from the keyboard
  252. /*         returns ABORT if aborted, non-zero on success
  253. /************************************************************************/
  254.  
  255. ftpgets(s,lim,echo)
  256.     char *s;        /* where to put the line */
  257.     short lim,echo;        /* max chars to read, echo? */
  258.     {
  259.     int count,i,cmd_status;
  260.     unsigned char c;
  261.     char *save, *ret;
  262.     Boolean gotOne;            /* Did we get an event */
  263.     EventRecord myEvent;    /* Event Record for this loop */
  264.  
  265.     count = 0;        /* none read */
  266.     save = s;        /* beginning of line */
  267.  
  268.     if (!fromtty) {
  269.        if (fromfp==NULL) {
  270.         ret = fgets(s,lim,stdin);
  271.        }
  272.        else {
  273.         ret = fgets(s,lim,fromfp);
  274.        }
  275.        if (ret==NULL) {
  276.             nputs("EOF or error on read from file\012");
  277.             cmd_status = ftpdo(scrn,"QUIT","");
  278.             netclose(screens[scrn].port);
  279.             destroyport( scrn);
  280.             exit(1);
  281.        }
  282.        s[strlen(s)-1] = '\0';    /* remove newline */
  283.        if (echo && fromfp) nputs(s);
  284.        return (strlen(s));
  285.     }
  286.     while (1) {
  287.  
  288.         if (Juggling)
  289.             gotOne = WaitNextEvent(everyEvent, &myEvent, JuggTicks, 0L);
  290.         else
  291.             gotOne = GetNextEvent(everyEvent, &myEvent);
  292.  
  293.         if ((myEvent.what == keyDown) || (myEvent.what == autoKey))
  294.             c = myEvent.message & charCodeMask;
  295.         else {
  296.             DoModem();            /* BYU 2.4.15 */
  297.             Stask();            /* BYU 2.4.15 */
  298.             DoNetEvents();        /* process event queue */
  299.             c = 0;
  300.         }
  301.  
  302.         switch (c) {        /* allow certain editing chars */
  303.             case 8:        /* backspace */
  304.                 if (count) {
  305.                     if (echo) {
  306.                         parse( &screens[scrn],&c,1);
  307.                         parse( &screens[scrn],(unsigned char *) " ",1);
  308.                         parse( &screens[scrn],&c,1);
  309.                     }
  310.                     count--;    /* one less character */
  311.                     s--;        /* move pointer backward */
  312.                 }
  313.                 break;
  314.             case 13:        /* carriage return, = ok */
  315.                 if (echo) putstring(scrn,"\015\012");    /* newline */
  316.                 *s = '\0';    /* terminate the string */
  317.                 return(c);    /* return ok */
  318.                 break;
  319.             case 21:        /* kill line */
  320.                 for (i=0; i < s-save; i++) {    /* length of line */
  321.                     if (echo) {        /* erase */
  322.                         parse( &screens[scrn],(unsigned char *) &backspace,1);
  323.                         parse( &screens[scrn],(unsigned char *) " ",1);
  324.                         parse( &screens[scrn],(unsigned char *) &backspace,1);
  325.                     }
  326.                 }
  327.                 s = save;    /* reset line */
  328.                 break;
  329.             case 0:            /* do nothing */
  330.                 break;
  331.             default:        /* not special char */
  332.                 if (c > 31 && c < 127) {    /* printable */
  333.                     if (echo) parse( &screens[scrn],&c,1);    /* display */
  334.                     *s++ = c;    /* add to string */
  335.                     count++;    /* length of string */
  336.                 }
  337.                 else        /* acts as eol */
  338.                     return(c);    /* value of special char */
  339.  
  340.                 if (count == lim) {    /* to length limit */
  341.                     *s = '\0';    /* terminate */
  342.                     return(c);    
  343.                 }
  344.             break;
  345.         }
  346.  
  347.     }
  348. }
  349.  
  350. /************************************************************************/
  351. /* captcon
  352. *  capture everything from a connection into the capture list
  353. *  return -1 on closed connection, else 0, 1 if paused
  354. /************************************************************************/
  355.  
  356. captcon(cnum,mywindow) int cnum,mywindow; {
  357.     int capturesize,cnt = 0;
  358.     unsigned char s[80];                /* temporary string */
  359.  
  360. /*    if (fromtty && n_scrlck()) return(TRUE);    /* if paused, nothing to do */
  361.     capturesize = screens[mywindow].capturesize;
  362.     do {
  363.         cnt = netread(cnum,&s[0],64);    /* get some from queue */
  364.         if ((cnt + capturesize) < captlistsize) {
  365.             BlockMove(&s[0],&captlist[capturesize],(long)cnt);
  366.             capturesize += cnt;
  367.         }
  368.  
  369. /* demux all packets */
  370.     } while ((cnt > 0) && ((cnt + capturesize) < captlistsize));
  371.  
  372.     captlist[capturesize] = 0;
  373.     screens[mywindow].capturesize = capturesize;
  374.  
  375.     return(cnt);            /* 0 normally, -1 if connection closed */
  376. }
  377.  
  378.  
  379. /************************************************************************/
  380. /*  telnet
  381. *   filter telnet options on incoming data
  382. /************************************************************************/
  383.  
  384. telnet(port,cnt,s) int port,cnt; unsigned char *s; {
  385. register int i,mylen,myport;
  386. char printline[256];        /* line to display */
  387.  
  388.     myport = WindByPort(port);
  389.     for (i=0; i < cnt; i++) {            /* put on screen */
  390.         if (*(s+i) & 128) {                /* if over ASCII 128 */
  391.             sprintf(printline," %d ",*(s+i));    /* show as number */
  392.             mylen = strlen(printline);
  393.             parse( &screens[myport],(unsigned char *) &printline[0],mylen);
  394.         }
  395.         else
  396.             parse( &screens[myport],(s+i),1);
  397.     }
  398.     return(TRUE);        
  399. }
  400.  
  401.  
  402. /************************************************************************/
  403. /* dumpcon
  404. *  take everything from a connection and send it to the screen
  405. *  return -1 on closed connection, else 0, 1 if paused
  406. /************************************************************************/
  407.  
  408. int dumpcon(cnum,mywindow) int cnum,mywindow; {        /* BYU 2.4.12 */
  409.     short i1,i2,cnt = 0,result=0;                    /* BYU 2.4.12 */
  410.     unsigned char s1[64],s2[128];                    /* temporary strings */
  411.  
  412. /*    if (fromtty && n_scrlck()) return(TRUE);        /* if paused, nothing to do */
  413.  
  414.     do {
  415.         cnt = netread(cnum,&s1[0],64);                /* get some from queue */
  416.  
  417. /* Search the incoming data for status codes and newlines */
  418.         i1 = 0;
  419.         i2 = 0;
  420.         while (i1 < cnt) {
  421.  
  422. /* Check for 3 digit codes beginning with "5" at the beginning of each line. */
  423.           if (s1[i1] == '\012' || s1[i1] == '\015') {        /* BYU 2.4.12 */
  424.               response_count[mywindow] = 0;                    /* BYU 2.4.12 */
  425.           } else if (response_count[mywindow] < 4) {                        /* BYU 2.4.12 */
  426.             response_data[mywindow][response_count[mywindow]++] = s1[i1];    /* BYU 2.4.12 */
  427.             if (response_count[mywindow] == 4) {                            /* BYU 2.4.12 */
  428.               if (response_data[mywindow][0] == '5' &&        /* BYU 2.4.12 */
  429.                   response_data[mywindow][1] >= '0' &&         /* BYU 2.4.12 */
  430.                   response_data[mywindow][1] <= '9' &&        /* BYU 2.4.12 */
  431.                   response_data[mywindow][2] == '0' &&         /* BYU 2.4.12 */
  432.                   response_data[mywindow][2] <= '9' &&        /* BYU 2.4.12 */
  433.                   response_data[mywindow][3] == ' ')        /* BYU 2.4.12 */
  434.                   result = -1;            /* BYU 2.4.12 - Abort indicated by other host */
  435.           } }
  436.  
  437. /* If a "newline" is found then force a "carriage return" immediately. */
  438.           if ('\012' == (s2[i2++] = s1[i1++]))
  439.             s2[i2++] = '\015';
  440.         }
  441.  
  442.         telnet(cnum,i2,&s2[0]);            /* display on screen, etc.*/
  443.  
  444. /* demux all packets */
  445.     } while (cnt > 0);
  446.  
  447.     return(result);            /* BYU 2.4.12 - 0 normally, -1 if connection closed */
  448. }
  449.  
  450.  
  451. /************************************************************************/
  452. /* getword: remove a word from a string.  Things within quotes are
  453. * assumed to be one word.
  454. * return TRUE on success, FALSE on end of string
  455. /************************************************************************/
  456.  
  457. getword(string,word) char *string,*word; {
  458. char *p,*q;
  459. int i=0;
  460.  
  461. p = stpblkp(string);            /* skip leading blanks */
  462. if (!(*p)) {                /* no words in string */
  463.     word[0] = '\0';
  464.     return(FALSE);
  465. }
  466. if (*p=='!') {                /* ! is a word */
  467.     word[0] = *p;
  468.     word[1] = '\0';
  469.     strcpy(string,++p);
  470.     return(TRUE);
  471. }
  472. if (*p=='\"') {                /* word delimited by quotes */
  473.     while (p[++i] && p[i]!='\"') word[i-1] = p[i];
  474.     word[i-1] = '\0';
  475.     if (!p[i]) nputs("Missing \". Assumed at end of string.");
  476.     else i++;
  477.     q = p+i;
  478. }
  479. else q = stptok(p, word, 50, " \t\015\012"); /* get word, max len 50 */
  480. p = stpblkp(q);                /* remove trailing blanks */
  481. strcpy(string,p);            /* remove extracted stuff */
  482. return(TRUE);
  483. }
  484.  
  485.  
  486. /************************************************************************/
  487. /* lowercase: convert a string to lowercase
  488. *
  489. /************************************************************************/
  490.  
  491. lowercase(word) char *word; {
  492. int i;
  493.  
  494. for (i=0; word[i]=tolower(word[i]); i++);
  495. return(TRUE);
  496. }
  497.  
  498.  
  499. /************************************************************************/
  500. /* finduniq: find name that is a unique prefix of one of the entries in
  501. * a list.  Return position of the entry, NONE if none, AMBIGUOUS if more
  502. * than one.
  503. *
  504. /************************************************************************/
  505.  
  506. int finduniq(name,listsize) unsigned char *name; int listsize; {
  507. int i,j=NONE,len;
  508. unsigned char *p,cmdstring[256];
  509.  
  510. len = strlen((char *) name);
  511. for (i=0; i<listsize; i++) {
  512.     GetIndString(cmdstring,FTPCOMMANDS,i+1);
  513.     p = (unsigned char *) p2cstr(cmdstring);
  514.     if (!strncmp((char *) name,(char *) cmdstring,len)) {        /* prefix */
  515.         if (len==strlen((char *) cmdstring)) return(i+1);    /* exact match */
  516.         if (j!=NONE) j = AMBIGUOUS;            /* more than one match */
  517.         else j = i+1;                        /* note prefix found */
  518.     }
  519. }
  520. return(j);            /* prefix */
  521. }
  522.  
  523.  
  524. /************************************************************************/
  525. /* checkoredir: check for output redirection.  If the command contains a
  526. * >, assume a filename follows and extract it.  Remove the redirection
  527. * from the original command.
  528. * Also change \ to /
  529. * return TRUE if redirection specified, FALSE otherwise 
  530. /************************************************************************/
  531.  
  532. checkoredir(command,filename,slashflip)
  533. char *command,*filename;
  534. int slashflip;
  535. {
  536. int i;
  537.  
  538.   filename[0] = '\0';
  539.   for (i=0; (command[i]!='>'); i++) {    /* process command part */
  540.     if (slashflip && command[i] == '\\') command[i] = '/';
  541.         if (!command[i]) return(FALSE);    /* no redirection */
  542.   }
  543.   getword(&command[i+1],filename);    /* get redirected filename */
  544.   command[i] = '\0';
  545.   return(TRUE);
  546. }
  547.  
  548.  
  549. /************************************************************************/
  550. /* getnname: get next name from captured list
  551. * names delimited by newlines - <CR> or <LF>
  552. /************************************************************************/
  553.  
  554. getnname(string,word) char *string,*word; {
  555. char *s;
  556.  
  557. s = string;
  558. while ((*string=='\012') || (*string=='\015')) string++;    /* skip initial newlines */
  559. if (!(*string)) return(FALSE);        /* end of captlist */
  560. while ((*string!='\012') && (*string!='\015') && (*string)) *(word++) = *(string++);
  561. while ((*string=='\012') || (*string=='\015')) string++;    /* skip trailing newline */
  562. *word = '\0';
  563. strcpy(s,string);
  564. return(TRUE);
  565. }
  566.  
  567.  
  568. /********************************************************************/
  569. /* FTP PI
  570. *  Protocol interpreter for user interface commands
  571. *  Will permit any command to be abbreviated uniquely.
  572. *  Recognizes commands, translates them to the protocol commands to be
  573. *  sent to the other server, and uses userftpd, the daemon, to do data
  574. *  transfers.
  575. /************************************************************************/
  576.  
  577. ftppi(command) char *command; {
  578. Boolean needanswer;
  579. int cmdno,i,cmd_status;
  580. char cmdname[20],word[PATHLEN],line[MAXFTP],answer[20],ofilename[PATHLEN];
  581. char *p,*getWDname();
  582. unsigned char destname[50];    /* who to connect to */
  583. char printline[256];        /* line to display */
  584.  
  585.     if (captlist == 0) {
  586.         captlist = (unsigned char *) NewPtr( (long) captlistsize);
  587. /*        newfile = (unsigned char *) NewPtr( (long) PATHLEN);        /* Pointer, no allocation necessary */
  588.         transfile = (unsigned char *) NewPtr( (long) PATHLEN);
  589.         xs = (unsigned char *) NewPtr( (long) (BUFFERS+10));
  590.     }
  591.  
  592. /* Indicates waiting for response */            /* BYU 2.4.12 */
  593.     response_count[scrn] = 0;                    /* BYU 2.4.12 */
  594.  
  595. /* get command number */
  596. if (!getword(command,cmdname)) return(FALSE);    /* get command name */
  597.  
  598. /* removes first word from command */
  599. lowercase(cmdname);
  600. cmdno = finduniq((unsigned char *) cmdname,NCMDS);    /* search cmdlist for prefix */
  601. if (cmdno==AMBIGUOUS) {        /* not unique abbreviation */
  602.     putstring(scrn,"?Ambiguous command\015\012");
  603.     return(FALSE);
  604. }
  605. if (cmdno==NONE) {        /* not a prefix of any command */
  606.     putstring(scrn,"?Invalid command\015\012");
  607.     return(FALSE);
  608. }
  609.  
  610.         /* change \ to / and check if command output redirected */
  611. if (cmdno!=BANG) {        /* don't alter shell escape */
  612.     if (cmdno!=LLS)        /* do not flip slashes for LLS */
  613.         checkoredir(command,ofilename,slashflip);    /* check redirection, flip \ */
  614.     else
  615.         checkoredir(command,ofilename,FALSE);        /* check redirection */
  616. }
  617.  
  618.     /* process commands */
  619. switch (cmdno) {
  620.     case QMARK:
  621.     case HELP:
  622.         if (!command[0]) {    /* no argument */
  623.             putstring(scrn,"Commands may be abbreviated:\015\012");
  624.  
  625.             /* display command list */
  626.             printline[0] = '\0';
  627.             for (i=2; i<NCMDS; i++) {
  628.                 GetIndString(word,FTPCOMMANDS,i+1);
  629.                 p = p2cstr(word);
  630.                 sprintf(word,"%-16s",word);    /* get word from list */
  631.                 strcat(printline,word);        /* add to line */
  632.                 if ((i-2)%5==4) {            /* display line */
  633.                     printline[79] = '\0';
  634.                     putstring(scrn,printline);
  635.                     putstring(scrn,"\015\012");
  636.                     printline[0] = '\0';
  637.                 }
  638.             }
  639.             if (i%5!=4) {
  640.                 putstring(scrn,printline);    /* last line */
  641.                 putstring(scrn,"\015\012");
  642.             }
  643.             return(TRUE);
  644.         }
  645.  
  646.             /* help for specific commands */
  647.         else {
  648.             while (getword(command,word)) {    /* loop for all args */
  649.                 i = finduniq((unsigned char *) word,NCMDS);   /* which command? */
  650.                 if (i==AMBIGUOUS)    /* non-unique command name */
  651.                     sprintf(printline,"?Ambiguous help command %s",word);
  652.                 else if (i==NONE)    /* no such command */
  653.                     sprintf(printline,"?Invalid help command %s",word);
  654.                 else {            /* display help string */
  655.                     GetIndString(printline,HELPRESID,i);
  656.                     p = p2cstr(printline);
  657.                 }
  658.                 putstring(scrn,printline);
  659.                 putstring(scrn,"\015\012");
  660.             }
  661.             return(TRUE);
  662.         }
  663.         break;
  664.     case BANG:        /* shell escape */
  665. #if 0
  666.         if (*(stpblkp(command))) {    /* command specified */
  667.             system(command);    /* execute command */
  668.             return(TRUE);
  669.         }
  670.         dosescape();        /* subshell */
  671. #endif
  672.         return(TRUE);
  673.     case BELL:
  674.         if (getword(command,word)) {    /* scan arg */
  675.             lowercase(word);
  676.             if (!strcmp(word,"off")) bell = FALSE;
  677.             else if (!strcmp(word,"on")) bell = TRUE;
  678.             else bell = !bell;
  679.         }
  680.         else bell = !bell;
  681.         if (bell) nputs("Bell mode on.");
  682.         else nputs("Bell mode off.");
  683.         return(TRUE);
  684.     case BYE:
  685.     case QUIT:
  686.         cmd_status = ftpdo(scrn,"QUIT",ofilename);
  687.         netclose(screens[scrn].port);
  688.         destroyport( scrn);
  689.         return(TRUE);
  690.     case DEBUG:        /* turn on/off debugging, optional level */
  691.         if (debug) {
  692.             debug = 0;
  693.             nputs("Debug off");
  694.         } else {
  695.             debug = 1;
  696.             nputs("Debug on");
  697.         }
  698.         return(TRUE);
  699.     case GLOB:        /* wildcard expansion */
  700.         if (getword(command,word)) {
  701.             lowercase(word);
  702.             if (!strcmp(word,"off")) glob = FALSE;
  703.             else if (!strcmp(word,"on")) glob = TRUE;
  704.             else glob = !glob;
  705.         }
  706.         else glob = !glob;
  707.         if (glob) nputs("Globbing on.");
  708.         else nputs("Globbing off.");
  709.         return(TRUE);
  710.     case HASH:        /* hash mark printing */
  711.         if (getword(command,word)) {
  712.             lowercase(word);
  713.             if (!strcmp(word,"off")) hash = FALSE;
  714.             else if (!strcmp(word,"on")) hash = TRUE;
  715.             else hash = !hash;
  716.         }
  717.         else hash = !hash;
  718.         if (hash) nputs("Hash mark printing on (1024 bytes/hash mark).");
  719.         else nputs("Hash printing off.");
  720.         return(TRUE);
  721.     case INTERACTIVE:    /* prompting on multiple transfers */
  722.         prompt = TRUE;
  723.         putstring(scrn,"Interactive mode on.\015\012");
  724.         return(TRUE);
  725.     case LCD:        /* change local directory */
  726.         if (*(stpblkp(command))) {                        /* BYU 2.4.17 - CD */
  727.             getword(command,word);                        /* BYU 2.4.17 */
  728.             if (chgdir(word))                            /* BYU 2.4.17 */
  729.             putstring(scrn,"Unable to change directory\015\012");
  730.         }
  731.         p = getWDname();    /* current directory */
  732.         p = p2cstr(p);
  733.         sprintf(printline,"Local directory now %s\015\012",p);
  734.         putstring(scrn,printline);
  735.         return(TRUE);
  736.     case LDIR:        /* local DIR */
  737.     case LLS:
  738.         if (!(*(stpblkp(command)))) {            /* null response ok */
  739.             p = getWDname();    /* current directory */
  740.             p2cstr(p);
  741.             sprintf(line,"*");
  742.         } else {
  743.             p = command;
  744.             sprintf(line,"%s",command);
  745.         }
  746.         putstring(scrn,"Directory "); 
  747.         putstring(scrn,p);
  748.         putstring(scrn,"\015\012");
  749.         if (NULL == (newfile = (unsigned char *) firstname(&line[0]))) {
  750.             putstring(scrn,"No files found\015\012");
  751.         } else {
  752.             putstring(scrn,(char *) newfile);
  753.             putstring(scrn,"\015\012");
  754.             while (NULL != (newfile = (unsigned char *) nextname())) {
  755.                 putstring(scrn,(char *) newfile);
  756.                 putstring(scrn,"\015\012");
  757.         } }
  758.         return(TRUE);
  759.     case NONINTERACTIVE:    /* turn off interactive prompting */
  760.         prompt = FALSE;
  761.         nputs("Interactive mode off.");
  762.         return(TRUE);
  763.     case OPEN:        /* open connection to host */
  764.         setupport();        /* Open a connection */
  765.         return(TRUE);
  766.     case PROMPT:            /* interactive prompting */
  767.         if (getword(command,word)) {
  768.             lowercase(word);
  769.             if (!strcmp(word,"off")) prompt = FALSE;
  770.             else if (!strcmp(word,"on")) prompt = TRUE;
  771.             else prompt = !prompt;
  772.         }
  773.         else prompt = !prompt;
  774.         if (prompt) nputs("Interactive mode on.");
  775.         else nputs("Interactive mode off.");
  776.         return(TRUE);
  777.     case SENDPORT:            /* send PORT commands for each transfer */
  778.         if (getword(command,word)) {
  779.             lowercase(word);
  780.             if (!strcmp(word,"off")) sendport = FALSE;
  781.             else if (!strcmp(word,"on")) sendport = TRUE;
  782.             else sendport = !sendport;
  783.         }
  784.         else sendport = !sendport;
  785.         if (sendport) nputs("Use of PORT cmds on.");
  786.         else nputs("Use of PORT cmds off.");
  787.         return(TRUE);
  788.     case SLASHFLIP:            /* change \ to / */
  789.         if (getword(command,word)) {
  790.             lowercase(word);
  791.             if (!strcmp(word,"off")) slashflip = FALSE;
  792.             else if (!strcmp(word,"on")) slashflip = TRUE;
  793.             else slashflip = !slashflip;
  794.         }
  795.         else slashflip = !slashflip;
  796.         if (slashflip) nputs("Slash translation on.");
  797.         else nputs("Slash translation off.");
  798.         return(TRUE);
  799.     case STATUS:        /* display status info */
  800.         sprintf(printline,"Connected to %s",destname);
  801.         nputs(printline);
  802.         if (ftpfilemode==FASCII) nputs("Transfer mode is ascii.");
  803.         else nputs("Transfer mode is binary.");
  804.         if (bell) nputs("Bell on."); else nputs("Bell off.");
  805.         if (debug) {
  806.             nputs("Debug on");
  807.         }
  808.         else nputs("Debug off");
  809.         if (glob) nputs("Filename globbing on."); else nputs("Filename globbing off.");
  810.         if (hash) nputs("Hash-mark printing on."); else nputs("Hash-mark printing off.");
  811.         if (prompt) nputs("Interactive prompting on."); else nputs("Interactive prompting off.");
  812.         if (sendport) nputs("Sending of port commands on."); else nputs("Sending of PORT cmds off.");
  813.         if (slashflip) nputs("Flipping \\ to / on."); else nputs("Flipping \\ to / off.");
  814.         if (verbose) nputs("Verbose mode on."); else nputs("Verbose mode off.");
  815.  
  816.         nputs("\012Remote status:");
  817.         cmd_status = ftpdo(scrn,"STAT",ofilename);
  818.  
  819.         return(TRUE);
  820.     case VERBOSE:        /* display informative messages */
  821.         if (getword(command,word)) {
  822.             lowercase(word);
  823.             if (!strcmp(word,"off")) verbose = FALSE;
  824.             else if (!strcmp(word,"on")) verbose = TRUE;
  825.             else verbose = !verbose;
  826.         }
  827.         else verbose = !verbose;
  828.         if (verbose) nputs("Verbose mode on.");
  829.         else nputs("Verbose mode off.");
  830.         return(TRUE);
  831.     default:        /* The other commands valid only if connected (we always are here) */
  832.       switch (cmdno) {
  833.       case ACCT:            /* get file in binary mode */
  834.         while (!(*(stpblkp(command)))) {
  835.             putstring(scrn,"Acct: ");
  836.             if (ftpgets(command,100,1)==ABORT) return(FALSE);
  837.         }
  838.         sprintf(line,"ACCT %s",command);
  839.         cmd_status = ftpdo(scrn,line,ofilename);        /* get file */
  840.         return(TRUE);
  841.       case ASCII:            /* transfer mode */
  842.         cmd_status = ftpdo(scrn,"TYPE A",ofilename);
  843.         return(TRUE);
  844.       case MACB:            /* transfer mode */
  845.           if (MacBinary) {
  846.             MacBinary = 0;
  847.             cmd_status = ftpdo(scrn,"MACB D",ofilename);
  848.         } else {
  849.             MacBinary = 1;
  850.             cmd_status = ftpdo(scrn,"MACB E",ofilename);
  851.         }
  852.         return(TRUE);
  853.       case BGET:            /* get file in binary mode */
  854.         i = ftpfilemode;    /* save current mode */
  855.         if (i==FASCII) cmd_status = ftpdo(scrn,"TYPE I",ofilename);
  856.         while (!(*(stpblkp(command)))) {
  857.             putstring(scrn,"File: ");
  858.             if (ftpgets(command,100,1)==ABORT) return(FALSE);
  859.         }
  860.         sprintf(line,"RETR %s",command);
  861.         cmd_status = ftpdo(scrn,line,ofilename);        /* get file */
  862.         if (i==FASCII) cmd_status = ftpdo(scrn,"TYPE A",ofilename);    /* restore mode */
  863.         return(TRUE);
  864.       case BINARY:        /* binary mode */
  865.         cmd_status = ftpdo(scrn,"TYPE I",ofilename);
  866.         return(TRUE);
  867.       case BPUT:            /* put file in binary mode */
  868.         i = ftpfilemode;
  869.         if (i==FASCII) cmd_status = ftpdo(scrn,"TYPE I",ofilename);
  870.         while (!(*(stpblkp(command)))) {        /* if no arg */
  871.             putstring(scrn,"File: ");    /* get from user */
  872.             if (ftpgets(command,100,1)==ABORT) return(FALSE);
  873.         }
  874.         sprintf(line,"STOR %s",command);
  875.         cmd_status = ftpdo(scrn,line,ofilename);
  876.         if (i==FASCII) cmd_status = ftpdo(scrn,"TYPE A",ofilename);
  877.         return(TRUE);
  878.       case CD:        /* change remote directory */
  879.         while (!(*(stpblkp(command)))) {        /* if no arg, get from user */
  880.             putstring(scrn,"To: ");
  881.             if (ftpgets(command,100,1)==ABORT) return(FALSE);    /* abort */
  882.         }
  883.         getword(command,word);
  884.         if (!strcmp(word,"..")) {    /* special case */
  885.             cmd_status = ftpdo(scrn,"CDUP",ofilename);
  886.             if (cmd_status!=ERROR) return(TRUE);        /* if CDUP understood */
  887. #if 0
  888.             nputs("Trying again...");
  889.             cmd_status = ftpdo(scrn,"XCUP",ofilename);    /* try alternative */
  890.             if (cmd_status!=ERROR) return(TRUE);
  891.             nputs("Trying again...");        /* else try usual CD */
  892. #endif
  893.         }
  894.         sprintf(line,"CWD %s",word);        /* try CWD */
  895.         cmd_status = ftpdo(scrn,line,ofilename);
  896.         if (cmd_status!=ERROR) return(TRUE);
  897. #if 0
  898.         nputs("Trying again...");
  899.         sprintf(line,"XCWD %s",word);        /* try XCWD */
  900.         cmd_status = ftpdo(scrn,line,ofilename);
  901. #endif
  902.         return(TRUE);
  903.       case CLOSE:                /* drop connection */
  904.         cmd_status = ftpdo(scrn,"QUIT",ofilename);
  905.         netclose(screens[scrn].port);
  906.         destroyport( scrn);
  907.         return(TRUE);
  908.       case DEL:
  909.       case RM:
  910.         getword(command,word);
  911.         while (!word[0]) {    /* get arg from user */
  912.             putstring(scrn,"File: ");
  913.             if (ftpgets(word,100,1)==ABORT) return(FALSE);    /* abort */
  914.         }
  915.         if (prompt) {        /* check interactively */
  916.             sprintf(printline,"Delete %s? ",word);
  917.             putstring(scrn,printline);
  918.             ftpgets(answer,20,1);
  919.             if (tolower(*(stpblkp(answer)))!='y') return(TRUE);
  920.         }
  921.         sprintf(line,"DELE %s",word);
  922.         cmd_status = ftpdo(scrn,line,ofilename);
  923.         return(TRUE);
  924.       case DIR:        /* get list of remote files */
  925.         if (ftpfilemode==FIMAGE) {
  926.             cmd_status = ftpdo(scrn,"TYPE A",ofilename);
  927.             if (getword(command,word)) {
  928.                 sprintf(line,"LIST %s",word);
  929.             } else sprintf(line,"LIST");
  930.             strcpy(screens[scrn].ftpbuf,line);
  931.             screens[scrn].clientflags = TYPE_I_ON_CLOSE;
  932.             screens[scrn].ftpstate = 3;        /* Do "LIST" when "TYPE" is finished */
  933.             screens[scrn].ftpnext = 1;
  934.         } else {
  935.             if (getword(command,word)) {    /* Do DIR */
  936.                 sprintf(line,"LIST %s",word);
  937.                 cmd_status = ftpdo(scrn,line,ofilename);
  938.             } else cmd_status = ftpdo(scrn,"LIST",ofilename);
  939.         }
  940.         return(TRUE);
  941.       case GET:
  942.       case RECV:        /* get remote file */
  943.         while (!(*(stpblkp(command)))) {        /* if no arg */
  944.             putstring(scrn,"File: ");
  945.             if (ftpgets(command,100,1)==ABORT) return(FALSE);    /* abort */
  946.         }
  947.         sprintf(line,"RETR %s",command);
  948.         cmd_status = ftpdo(scrn,line,ofilename);
  949.         return(TRUE);
  950.       case LS:        /* get remote file list - short */
  951.         if (ftpfilemode==FIMAGE) {
  952.             cmd_status = ftpdo(scrn,"TYPE A",ofilename);
  953.             if (getword(command,word)) {
  954.                 sprintf(line,"NLST %s",word);
  955.             } else sprintf(line,"NLST");
  956.             strcpy(screens[scrn].ftpbuf,line);
  957.             screens[scrn].clientflags = TYPE_I_ON_CLOSE;
  958.             screens[scrn].ftpstate = 3;        /* Do "NLST" when "TYPE" is finished */
  959.             screens[scrn].ftpnext = 1;
  960.         } else {
  961.             if (getword(command,word)) {
  962.                 sprintf(line,"NLST %s",word);
  963.                 cmd_status = ftpdo(scrn,line,ofilename);
  964.             } else cmd_status = ftpdo(scrn,"NLST",ofilename);
  965.         }
  966.         return(TRUE);
  967.       case MDELETE:
  968.         while (!(*(stpblkp(command)))) {        /* no arg */
  969.             putstring(scrn,"Files: ");
  970.             if (ftpgets(command,100,1)==ABORT) return(FALSE);    /* abort */
  971.         }
  972.         while (getword(command,word)) {        /* for each arg */
  973.             if (glob) {        /* wildcard expansion */
  974.                 sprintf(line,"NLST %s",word);
  975.                 screens[scrn].clientflags |= CAPTURE_DATA;
  976.                 cmd_status = ftpdo(scrn,line,ofilename);    /* put exapnsion in captlist */
  977.             }
  978.             else strcpy((char *) captlist,word);    /* captlist has name(s) now */
  979.             while (getnname((char *) captlist,word)) {    /* for each name */
  980.                 if (prompt) {    /* check */
  981.                 sprintf(printline,"mdelete %s? ",word);
  982.                 putstring(scrn,printline);
  983.                 if (ftpgets(answer,20,1)==ABORT) {    /* abort */
  984.                 command[0] = '\0';    /* no more processing */
  985.                 break;            /* quit immediately */
  986.                 }
  987.                 if (tolower(*(stpblkp(answer)))!='y') continue;
  988.                 }
  989.                 sprintf(line,"DELE %s",word);    /* delete */
  990.                 cmd_status = ftpdo(scrn,line,ofilename);
  991.             }
  992.         }
  993.         return(TRUE);
  994.       case MDIR:        /* remote multiple DIR */
  995.         i = ftpfilemode;    /* save mode */
  996.         if (i==FIMAGE) cmd_status = ftpdo(scrn,"TYPE A",ofilename);
  997.         while (!(*(stpblkp(command)))) {        /* no arg */
  998.             putstring(scrn,"Directories: ");
  999.             if (ftpgets(command,100,1)==ABORT) return(FALSE);    /* abort */
  1000.         }
  1001.         while (getword(command,word)) {        /* for each arg */
  1002.             if (glob) {        /* expand wildcards */
  1003.                 sprintf(line,"NLST %s",word);
  1004.                 screens[scrn].clientflags |= CAPTURE_DATA;
  1005.                 cmd_status = ftpdo(scrn,line,ofilename);
  1006.             }
  1007.             else strcpy((char *) captlist,word);
  1008.             while (getnname((char *) captlist,word)) {    /* for each name */
  1009.                 if (prompt) {    /* check */
  1010.                 sprintf(printline,"mdir %s? ",word);
  1011.                 putstring(scrn,printline);
  1012.                 if (ftpgets(answer,20,1)==ABORT) {    /* abort */
  1013.                 command[0] = '\0';    /* no more processing */
  1014.                 break;            /* quit immediately */
  1015.                 }
  1016.                 if (tolower(*(stpblkp(answer)))!='y') continue;
  1017.                 }
  1018.                 sprintf(line,"LIST %s",word);    /* DIR */
  1019.                 cmd_status = ftpdo(scrn,line,ofilename);
  1020.             }
  1021.         }
  1022.         if (i==FIMAGE) cmd_status = ftpdo(scrn,"TYPE I",ofilename);
  1023.         return(TRUE);
  1024.       case MGET:                            /* get multiple files */
  1025.         getword(command,line);
  1026.         while (!line[0]) {                    /* no arg */
  1027.             putstring(scrn,"Files: ");
  1028.             if (ftpgets(line,100,1)==ABORT) return(FALSE);    /* abort */
  1029.         }
  1030.         if (getword(line,word)) {
  1031.             sprintf(command,"NLST %s",word);
  1032.             screens[scrn].clientflags |= CAPTURE_DATA;
  1033.             cmd_status = ftpdo(scrn,command,ofilename);
  1034.  
  1035.             screens[scrn].clientflags |= MGET_STATE;
  1036.         }
  1037.         return(TRUE);
  1038.       case MKDIR:                            /* create directory */
  1039.         while (!(*(stpblkp(command)))) {        /* no arg */
  1040.             putstring(scrn,"Directory: ");
  1041.             if (ftpgets(command,100,1)==ABORT) return(FALSE);    /* abort */
  1042.         }
  1043.         sprintf(line,"XMKD %s",command);    /* try XMKD */
  1044.         cmd_status = ftpdo(scrn,line,ofilename);
  1045.             if (cmd_status!=ERROR) return(TRUE);
  1046.         nputs("Trying again...");
  1047.         sprintf(line,"MKD %s",command);        /* else try MKD */
  1048.         cmd_status = ftpdo(scrn,line,ofilename);
  1049.         return(TRUE);
  1050.       case MLS:
  1051.         i = ftpfilemode;
  1052.         if (i==FIMAGE) cmd_status = ftpdo(scrn,"TYPE A",ofilename);
  1053.         while (!(*(stpblkp(command)))) {        /* no arg */
  1054.             putstring(scrn,"Directories: ");
  1055.             if (ftpgets(command,100,1)==ABORT) return(FALSE);    /* abort */
  1056.         }
  1057.         while (getword(command,word)) {        /* for each arg */
  1058.             if (glob) {        /* exapnd wildcards */
  1059.                 sprintf(line,"NLST %s",word);
  1060.                 screens[scrn].clientflags |= CAPTURE_DATA;
  1061.                 cmd_status = ftpdo(scrn,line,ofilename);
  1062.             }
  1063.             else strcpy((char *) captlist,word);
  1064.             while (getnname((char *) captlist,word)) {    /* for each name */
  1065.                 if (prompt) {        /* check */
  1066.                 sprintf(printline,"mls %s? ",word);
  1067.                 putstring(scrn,printline);
  1068.                 if (ftpgets(answer,20,1)==ABORT) {  /* abort */
  1069.                 command[0] = '\0';    /* no more processing */
  1070.                 break;            /* quit immediately */
  1071.                 }
  1072.                 if (tolower(*(stpblkp(answer)))!='y') continue;
  1073.                 }
  1074.                 sprintf(line,"NLST %s",word);    /* DIR */
  1075.                 cmd_status = ftpdo(scrn,line,ofilename);
  1076.             }
  1077.         }
  1078.         if (i==FIMAGE) cmd_status = ftpdo(scrn,"TYPE I",ofilename);
  1079.         return(TRUE);
  1080.       case MODE:        /* set stream mode */
  1081.         getword(command,word);
  1082.         lowercase(word);
  1083.         if (strncmp(word,"stream",strlen(word)))
  1084.             nputs("We only support stream mode, sorry.");
  1085.         else nputs("Mode is stream.");
  1086.         return(TRUE);
  1087.       case MPUT:        /* put multiple files */
  1088.         getword(command,(char *) captlist);
  1089.         while (!captlist[0]) {    /* no arg */
  1090.             putstring(scrn,"Files: ");
  1091.             if (ftpgets((char *) captlist,100,1)==ABORT) return(FALSE);    /* abort */
  1092.         }
  1093.         if (getword((char *) captlist,(char *) transfile)) {        /* for each arg */
  1094.           newfile = NULL;
  1095.           needanswer = TRUE;
  1096.           while (needanswer) {
  1097.             needanswer = FALSE;
  1098.             if (glob) {                                /* local wildcard expansion */
  1099.                 if (newfile == NULL) {                /* if no expansions yet */
  1100.                     newfile = (unsigned char *) firstname((char *) transfile);    /* get first name */
  1101.                     if (newfile == NULL) {            /* if no expansions */
  1102.                         sprintf(printline,"No match for %s",transfile);
  1103.                         nputs(printline);
  1104.                         if (getword((char *) captlist,(char *) transfile)) {
  1105.                             needanswer = TRUE;
  1106.                     }    }
  1107.                 } else {                            /* not first name */
  1108.                     newfile = (unsigned char *) nextname();    /* get next name */
  1109.                     if (newfile == NULL) {            /* if no names, next arg */
  1110.                         if (getword((char *) captlist,(char *) transfile)) {
  1111.                             needanswer = TRUE;
  1112.                 }    }    }
  1113.             } else newfile = transfile;                /* no expansion */
  1114.             if (newfile != NULL) {
  1115. #if 1    /* When prompting is fixed switch to the code below */
  1116.                 sprintf(command,"STOR \"%s\"",newfile);    /* name may have spl chars */
  1117.                 cmd_status = ftpdo(scrn,command,ofilename);
  1118.                 screens[scrn].clientflags |= MPUT_STATE;
  1119. #else
  1120.                 if (prompt) {                        /* check */
  1121.                     sprintf(printline,"mput %s? ",newfile);
  1122.                     putstring(scrn,printline);
  1123.                     if (ftpgets(answer,20,1)==ABORT) {    /* abort */
  1124.                         command[0] = '\0';                /* no more processing */
  1125.                         break;
  1126.                     } else if (tolower(*(stpblkp(answer))) == 'y') {
  1127.                         sprintf(command,"STOR \"%s\"",newfile);    /* name may have spl chars */
  1128.                         cmd_status = ftpdo(scrn,command,ofilename);
  1129.                         screens[scrn].clientflags |= MPUT_STATE;
  1130.                     }
  1131.                 } else {
  1132.                     sprintf(command,"STOR \"%s\"",newfile);    /* name may have spl chars */
  1133.                     cmd_status = ftpdo(scrn,command,ofilename);
  1134.                     screens[scrn].clientflags |= MPUT_STATE;
  1135.                 }
  1136. #endif
  1137.         } } }
  1138.         return(TRUE);
  1139.       case PUT:            
  1140.       case SEND:        /* put file */
  1141.         while (!(*(stpblkp(command)))) {        /* no args */
  1142.             putstring(scrn,"File: ");
  1143.             if (ftpgets(command,100,1)==ABORT) return(FALSE);
  1144.         }
  1145.         sprintf(line,"STOR %s",command);    /* put file */
  1146.         cmd_status = ftpdo(scrn,line,ofilename);
  1147.         return(TRUE);
  1148.       case PWD:
  1149. #if 0
  1150.         cmd_status = ftpdo(scrn,"XPWD",ofilename);        /* try XPWD */
  1151.             if (i!=ERROR) return(TRUE);
  1152.         nputs("Trying again...");
  1153. #endif
  1154.         cmd_status = ftpdo(scrn,"PWD",ofilename);            /* else try PWD */
  1155.         return(TRUE);
  1156.       case QUOTE:
  1157.         while (!(*(stpblkp(command)))) {        /* no arg */
  1158.             putstring(scrn,"Command: ");
  1159.             if (ftpgets(command,100,1)==ABORT) return(FALSE);
  1160.         }
  1161.         cmd_status = ftpdo(scrn,command,ofilename);        /* send command */
  1162.         return(TRUE);
  1163.       case REMOTEHELP:                /* get help */
  1164.         if (*(stpblkp(command))) {        /* for specific command */
  1165.             sprintf(line,"HELP %s",command);
  1166.             cmd_status = ftpdo(scrn,line,ofilename);
  1167.         }
  1168.         else cmd_status = ftpdo(scrn,"HELP",ofilename);        /* generic help */
  1169.         return(TRUE);
  1170.       case RENAME:        /* rename remote file */
  1171.         while (!(*(stpblkp(command)))) {        /* no arg */
  1172.             putstring(scrn,"From: ");
  1173.             if (ftpgets(command,100,1)==ABORT) return(FALSE);
  1174.         }
  1175.         getword(command,word);
  1176.         sprintf(line,"RNFR %s",word);
  1177.         cmd_status = ftpdo(scrn,line,ofilename);        /* send rename from name */
  1178.         while (!(*(stpblkp(command)))) {        /* no second arg */
  1179.             putstring(scrn,"To: ");
  1180.             if (ftpgets(command,100,1)==ABORT) {
  1181.             cmd_status = ftpdo(scrn,"ABOR",ofilename);
  1182.             return(FALSE);
  1183.             }
  1184.         }
  1185.         sprintf(line,"RNTO %s",command); /* send rename to name */
  1186.         cmd_status = ftpdo(scrn,line,ofilename);
  1187.         return(TRUE);
  1188.       case RMDIR:            /* remove remote dir */
  1189.         while (!(*(stpblkp(command)))) {        /* no arg */
  1190.             putstring(scrn,"Directory: ");
  1191.             if (ftpgets(command,100,1)==ABORT) return(FALSE);
  1192.         }
  1193.         sprintf(line,"XRMD %s",command);    /* try XRMD */
  1194.         cmd_status = ftpdo(scrn,line,ofilename);
  1195.             if (cmd_status!=ERROR) return(TRUE);
  1196.         nputs("Trying again...");
  1197.         sprintf(line,"RMD %s",command);        /* try RMD */
  1198.         cmd_status = ftpdo(scrn,line,ofilename);
  1199.         return(TRUE);
  1200.       case STRUCT:        /* set structure type - only file */
  1201.         getword(command,word);
  1202.         lowercase(word);
  1203.         if (strncmp(word,"file",strlen(word)))
  1204.             nputs("We only support file structure, sorry.");
  1205.         else nputs("Structure is file.");
  1206.         return(TRUE);
  1207.       case TYPE:        /* set transfer type */
  1208.         if (!getword(command,word)) {    /* no arg, just show */
  1209.            if (ftpfilemode==FASCII) nputs("Transfer type is ascii.");
  1210.            else nputs("Transfer type is binary.");
  1211.         }
  1212.         lowercase(word);
  1213.         if (!strncmp(word,"ascii",strlen(word)))
  1214.             cmd_status = ftpdo(scrn,"TYPE A",ofilename);
  1215.         else if (!strncmp(word,"binary",strlen(word)) ||
  1216.             !strncmp(word,"image",strlen(word)))
  1217.             cmd_status = ftpdo(scrn,"TYPE I",ofilename);
  1218.         else {
  1219.             sprintf(printline,"Unrecognized type: %s",word);
  1220.             nputs(printline);
  1221.         }
  1222.         return(TRUE);
  1223.       case USER:            /* login to remote machine */
  1224.         if (!(*(stpblkp(command)))) {    /* null response to prompt ok */
  1225.             putstring(scrn,"Username: ");
  1226.             if (ftpgets(command,100,1)==ABORT) return(FALSE);
  1227.         }
  1228.         sprintf(line,"USER %s",command);    /* username */
  1229.         if ((cmd_status = ftpdo(scrn,line,ofilename))==TRUE) return(TRUE);
  1230. #if 0
  1231.         putstring(scrn,"Password: ");
  1232. #endif
  1233.         if (ftpgets(word,PATHLEN,0)==ABORT) return(FALSE);        /* no echoing */
  1234.         sprintf(line,"PASS %s",word);        /* password */
  1235.         if ((cmd_status = ftpdo(scrn,line,ofilename))==INCOMPLETE) {    /* if account needed */
  1236.             do {
  1237.                 putstring(scrn,"Account: ");
  1238.                 if (ftpgets(command,100,1)==ABORT) return(FALSE);
  1239.             } while (!(*(stpblkp(command))));
  1240.             sprintf(line,"ACCT %s",command);
  1241.             cmd_status = ftpdo(scrn,line,ofilename);
  1242.         }
  1243.         return(TRUE);        
  1244.     default:    /* unknown command */
  1245.         putstring(scrn,"?Invalid command\015\012");
  1246. #if 0
  1247.         sprintf(printline,"***Unknown command no: %d",cmdno);
  1248.         nputs(printline);
  1249. #endif
  1250.         break;
  1251.     }
  1252.     }
  1253. }
  1254.  
  1255.  
  1256. /************************************************************************/
  1257. /*   ftpport
  1258. *   return a new port number so that we don't try to re-use ports
  1259. *   before the mandatory TCP timeout period.  (lifetime of a packet)
  1260. *   use a time-based initial port selection scheme.
  1261. /************************************************************************/
  1262.  
  1263. ftpport(ftpscrn) int ftpscrn; {
  1264.     unsigned int i;
  1265.     unsigned char hostnum[5];
  1266.     char sendline[60];        /* for port command */
  1267. #if 0
  1268.     char printline[MAXFTP];        /* Debug - line to display */
  1269. #endif
  1270.  
  1271.     if (!sendport) {        /* default port */
  1272.         return(HFTP-1);
  1273.     }
  1274.     if (curftpprt < 40000) {    /* restart cycle */
  1275.         i = (unsigned int) TickCount();
  1276.         curftpprt = 40000 + (i & 0x3fff);
  1277.     }
  1278.  
  1279.     i = curftpprt--;    /* get port, update for next time */
  1280.  
  1281.     if (screens[ftpscrn].connectionType) {                            /* BYU 2.4.15 */
  1282.         hostnum[0] = SLIP_ip_number[0];                                /* BYU 2.4.15 */
  1283.         hostnum[1] = SLIP_ip_number[1];                                /* BYU 2.4.15 */
  1284.         hostnum[2] = SLIP_ip_number[2];                                /* BYU 2.4.15 */
  1285.         hostnum[3] = SLIP_ip_number[3];                                /* BYU 2.4.15 */
  1286.     } else                                                            /* BYU 2.4.15 */
  1287.         netgetip(hostnum);    /* get my ip number */                    /* BYU 2.4.15 */
  1288.  
  1289.     ftpdata = netlisten(i,screens[ftpscrn].connectionType);
  1290.     screens[ftpscrn].ftpport = ftpdata;
  1291.     Sptypes[ftpdata] = UDATA;
  1292.  
  1293. #if 0
  1294. if (debug) {
  1295.     sprintf(printline,"ftpport port: %d  ftpdata: %d",i,ftpdata);
  1296.     nputs(printline);
  1297. }
  1298. #endif
  1299.  
  1300.     sprintf(sendline,"PORT %d,%d,%d,%d,%d,%d\015\012",hostnum[0],hostnum[1],hostnum[2],
  1301.         hostnum[3],i/256,i&255);    /* full port number */
  1302.  
  1303.     netpush(screens[ftpscrn].port);    /* empty command connection */
  1304.     netwrite(screens[ftpscrn].port,sendline,strlen(sendline));    /* send PORT command */
  1305.  
  1306.     return(i);        /* port number */
  1307.  
  1308. }
  1309.  
  1310.  
  1311. /************************************************************************/
  1312. /* ftpdo
  1313. *  Do whatever command is sent from the user interface using
  1314. *  userftpd, the background file handler
  1315. /************************************************************************/
  1316.  
  1317. int ftpdo(ftpscrn,s,ofile) int ftpscrn; char *s,*ofile; {
  1318.     int i;
  1319.     char name[MAXFTP],name2[MAXFTP];
  1320.     char commandbuf[MAXFTP];
  1321.  
  1322. #if 0
  1323.     char printline[MAXFTP];        /* Debug - line to display */
  1324.  
  1325.     nputs("FTPDO - begin");
  1326. #endif
  1327.  
  1328.     strcpy(commandbuf,s);
  1329.     for (i=0; i<4; i++) {
  1330.         commandbuf[i] = toupper(commandbuf[i]);    /* command to upper case */
  1331.     }
  1332.  
  1333.     if (!strncmp(commandbuf,"STOR",4)) {    /* put file */
  1334.         getword(&commandbuf[5],name);    /* first arg - local file */
  1335.         if (!commandbuf[5]) strcpy(&commandbuf[5],name);        /* if only one argument */
  1336.             else {
  1337.             getword(&commandbuf[5],name2);    /* second arg - removes quotes etc. */
  1338.             strcpy(&commandbuf[5],name2);    /* copy back into command */
  1339.         }
  1340.  
  1341. #ifdef MACBINARY
  1342.         if ((ftp_mbfp = MBopen( &name[0], defaultv, MB_READ + (((!MacBinary) ||    /* BYU 2.4.18 */
  1343.             (ftpfilemode == FAMODE)) ? MB_DISABLE : 0))) == 0L) {
  1344.             putstring(ftpscrn,"Could not open file\015\012");
  1345.             return(-1);
  1346.         }
  1347.         ftpfh = 12;
  1348. #else
  1349.         if (0 > (ftpfh = open(&name[0],ftpfilemode))) {
  1350.             putstring(ftpscrn,"Could not open file\015\012");
  1351.             return(-1);
  1352.         }
  1353. #endif
  1354.  
  1355.         c2pstr(&name[0]);
  1356.         GetFileInfo(0,&name[0],&iop);
  1357.         filelen = iop.ioFlLgLen;
  1358.         if (MacBinary && (ftpfilemode == FIMODE)) filelen += iop.ioFlRLgLen;
  1359.  
  1360.         ftpport(ftpscrn);        /* open data connection */
  1361.         screens[ftpscrn].ftpstate = 2;
  1362.         screens[ftpscrn].ftpnext = 20;
  1363.         strcpy(screens[ftpscrn].ftpbuf,commandbuf);
  1364.         strcat(screens[ftpscrn].ftpbuf,"\015\012");
  1365.         return(1);
  1366.  
  1367.     }
  1368.     else if (!strncmp(commandbuf,"RETR",4)) {    /* get file */
  1369.         getword(&commandbuf[5],name);            /* remote file */
  1370.         if (commandbuf[5]) {        /* two args present */
  1371.             getword(&commandbuf[5],name2);    /* local file */
  1372.  
  1373. #ifdef MACBINARY
  1374.                 if ((ftp_mbfp = MBopen(&name2[0], defaultv, MB_WRITE +    /* BYU 2.4.18 */
  1375.                     (((!MacBinary) || (ftpfilemode == FAMODE)) ? MB_DISABLE : 0
  1376.                     ))) == 0L) {
  1377.                     putstring(ftpscrn,"Cannot open file to receive\015\012");
  1378.                     return(-1);
  1379.                 } else ftpfh = 12;
  1380. #else
  1381.  
  1382.                 if (0 > (ftpfh = creat(&name2[0],ftpfilemode))) {
  1383.                     putstring(ftpscrn,"Cannot open file to receive\015\012");
  1384.                     return(-1);
  1385.                 }
  1386. #endif
  1387.  
  1388.         } else {
  1389. #ifdef MACBINARY
  1390.                 if ((ftp_mbfp = MBopen(&name[0], defaultv, MB_WRITE +    /* BYU 2.4.18 */
  1391.                     (((!MacBinary) || (ftpfilemode == FAMODE)) ? MB_DISABLE : 0
  1392.                     ))) == 0L) {
  1393.                     putstring(ftpscrn,"Cannot open file to receive\015\012");
  1394.                     return(-1);
  1395.                 } else ftpfh = 12;
  1396. #else
  1397.  
  1398.                 if (0 > (ftpfh = creat(&name[0],ftpfilemode))) {
  1399.                     putstring(ftpscrn,"Cannot open file to receive\015\012");
  1400.                     return(-1);
  1401.                 }
  1402. #endif
  1403.         }
  1404.  
  1405.         strcpy(&commandbuf[5],name);            /* Put remote name back into command */
  1406.  
  1407.         ftpport(ftpscrn);        /* open data connection */
  1408.         screens[ftpscrn].ftpstate = 2;
  1409.         screens[ftpscrn].ftpnext = 30;
  1410.         strcpy(screens[ftpscrn].ftpbuf,commandbuf);
  1411.         strcat(screens[ftpscrn].ftpbuf,"\015\012");
  1412.         return(1);
  1413.  
  1414.     } else if (!strncmp(commandbuf,"LIST",4) || !strncmp(commandbuf,"NLST",4)) {
  1415.  
  1416.         if ((screens[ftpscrn].clientflags & CAPTURE_DATA) != 0)
  1417.             screens[ftpscrn].capturesize = 0;        /* Size of captured data */
  1418.  
  1419.         ftpport(ftpscrn);        /* data connection */
  1420.         screens[ftpscrn].ftpstate = 2;
  1421.         screens[ftpscrn].ftpnext = 40;
  1422.         strcpy(screens[ftpscrn].ftpbuf,commandbuf);
  1423.         strcat(screens[ftpscrn].ftpbuf,"\015\012");
  1424.         return(1);
  1425.  
  1426.     } else if (!strncmp(commandbuf,"TYPE",4)) {
  1427.         if (toupper(commandbuf[5]) == 'I')
  1428.             ftpfilemode = FIMAGE;                /* Remember mode */
  1429.         else if (toupper(commandbuf[5]) == 'A')
  1430.             ftpfilemode = FASCII;
  1431.  
  1432.     }
  1433.  
  1434.     netpush(screens[ftpscrn].port);
  1435.  
  1436.     strcat(commandbuf,"\015\012");                                    /* BYU 2.4.11 */
  1437.     netwrite(screens[ftpscrn].port,commandbuf,strlen(commandbuf));    /* BYU 2.4.11 - send command */
  1438.  
  1439.     if (((screens[ftpscrn].clientflags & CAPTURE_DATA) == 0) && ofile[0]) {        /* command redirected */
  1440.         if ((screens[ftpscrn].ftpstate != 20) && (screens[ftpscrn].ftpstate != 30)) {    /* not get or put */
  1441.             if (0 > (ftpfh = ftpopen(ofile)))
  1442.                 nputs(" Cannot open output file.");
  1443.             else if (ftpdata > -1) {
  1444.                 screens[ftpscrn].ftpstate = 30;    /* act as get, since data goes into file */
  1445.             } else {
  1446. /*                Close(ftpfh);        /* BYU LSC */
  1447.                 ftpfh = 0;
  1448.             }
  1449.         }
  1450.     }
  1451. #if 0
  1452. if (debug) {
  1453.     sprintf(printline,"---> %s",commandbuf);    /* show command sent */
  1454.     nputs(printline);
  1455. }
  1456. #endif
  1457.     return(FALSE);
  1458. }
  1459.  
  1460.  
  1461. /************************************************************************/
  1462. /* userftpd
  1463. *  FTP receive and send file functions
  1464. /************************************************************************/
  1465.  
  1466. userftpd(code,myport) int code,myport; {
  1467.     Boolean needanswer;
  1468.     long mytime;
  1469.     int cmd_status,connection_status,ftpstate,i,mycode,myftpdata,mytelport,mywindow;
  1470.     char command[MAXFTP],printline[MAXFTP],word[MAXFTP];
  1471. #if 0
  1472.     char answer[20];
  1473. #endif
  1474.  
  1475.     mycode = code;
  1476.  
  1477.     connection_status = 0;        /* BYU 2.4.12 - assume good connection status */
  1478.     ftpstate = 1;
  1479.     mywindow = WindByPort(myport);
  1480.     if (mywindow >= 0) {
  1481.       if (myport == screens[mywindow].port) {
  1482.         ftpstate = screens[mywindow].ftpstate;
  1483.         myftpdata = -1;
  1484.       } else {
  1485.         ftpstate = screens[mywindow].ftpstate;
  1486.         myftpdata = screens[mywindow].ftpport;
  1487.     } }
  1488.  
  1489.     if (mywindow < 0) return(0);
  1490. #if 0
  1491. if (debug) {
  1492.     sprintf(printline,"  %d %d %u twin: %d\015\012",ftpstate,mycode,myport,mywindow);
  1493.     putstring(mywindow,printline);
  1494. }
  1495. #endif
  1496.  
  1497.     mytelport = screens[mywindow].port;
  1498.  
  1499.     switch (ftpstate) {
  1500.         default:    /* unknown */
  1501.             break;
  1502.  
  1503.         case 1:
  1504.             if ((mycode == CONDATA) && (myport == mytelport)) 
  1505.                 connection_status = dumpcon(myport,mywindow);
  1506.             break;
  1507.  
  1508. /* Wait for response from "PORT" command, then send ftp command */
  1509.         case 2:
  1510.             if (mycode == CONDATA) {
  1511.                 connection_status = dumpcon(myport,mywindow);
  1512.                 netpush(screens[mywindow].port);
  1513.                 netwrite(screens[mywindow].port,screens[mywindow].ftpbuf,strlen(screens[mywindow].ftpbuf));    /* send command */
  1514.                 screens[mywindow].ftpstate = screens[mywindow].ftpnext;
  1515. #if 0
  1516. if (debug) {
  1517.     sprintf(printline,"---> %s",screens[mywindow].ftpbuf);    /* show command sent */
  1518.     nputs(printline);
  1519. }
  1520. #endif
  1521.             }
  1522.             break;
  1523.  
  1524. /* Wait for response from "TYPE" command, then send ftp command */
  1525.         case 3:
  1526.             if (mycode == CONDATA) {
  1527.                 connection_status = dumpcon(myport,mywindow);
  1528.                 cmd_status = ftpdo(mywindow,screens[mywindow].ftpbuf,"");
  1529. #if 0
  1530. if (debug) {
  1531.     sprintf(printline,"---> %s",screens[mywindow].ftpbuf);    /* show command sent */
  1532.     nputs(printline);
  1533. }
  1534. #endif
  1535.             }
  1536.             break;
  1537.  
  1538.         case 5:
  1539. /* Get the next file of an MGET. */
  1540.             if ((screens[mywindow].clientflags & CAPTURE_DATA) != 0) {
  1541.                 screens[mywindow].clientflags &= ~CAPTURE_DATA;
  1542.             }
  1543.  
  1544. /* After capturing the data, initiate the file transfer(s) */
  1545.             if ((screens[mywindow].clientflags & MGET_STATE) != 0) {
  1546.                 if (screens[mywindow].capturesize > 0) {
  1547.                     screens[mywindow].ftpstate = 6;
  1548.                     netputuev(CONCLASS,CONDATA,mytelport);    /* Stay alive to transfer file */
  1549.                 } else {
  1550.                     screens[mywindow].clientflags &= ~MGET_STATE;
  1551.                     screens[mywindow].ftpstate = 1;
  1552.             }    }
  1553.             break;
  1554.  
  1555. /* Receive one MGET file. */
  1556.         case 6:
  1557.             connection_status = dumpcon(myport,mywindow);
  1558.             if (getnname((char *) captlist,(char *) word)) {    /* for each name */
  1559. #if 0
  1560.                 if (prompt) {    /* check */
  1561.                     sprintf(printline,"mget %s? ",word);
  1562.                     putstring(mywindow,printline);
  1563.                     if (ftpgets(answer,20,1)==ABORT) {    /* abort */
  1564.                         command[0] = '\0';    /* no more processing */
  1565.                         break;            /* quit immediately */
  1566.                     }
  1567.                     if (tolower(*(stpblkp(answer)))!='y') continue;
  1568.                 } else {
  1569. #endif
  1570.                     sprintf(printline,"Receiving %s\015\013",word);
  1571.                     putstring(mywindow,printline);
  1572. #if 0
  1573.                 }
  1574. #endif
  1575.                 sprintf(command,"RETR \"%s\"",word);
  1576.                 if ((cmd_status = ftpdo(mywindow,command,"")) < 0) {
  1577.                     screens[mywindow].clientflags &= ~MGET_STATE;
  1578.                     screens[mywindow].ftpstate = 1;
  1579.                 }
  1580.             } else {
  1581.                 screens[mywindow].clientflags &= ~MGET_STATE;
  1582.                 screens[mywindow].ftpstate = 1;
  1583.             }
  1584.             break;
  1585.  
  1586. /* Send a file to the remote connection */
  1587.         case 20:
  1588.  
  1589.             if (mycode == CONFAIL) mycode = CONCLOSE;    /* something went wrong */
  1590.  
  1591.             if (mycode == CONOPEN) {
  1592.                 screens[mywindow].ftpstate = 21;
  1593.                 transtime = TickCount();
  1594.                 translen = 0;
  1595.                 towrite = 0;
  1596.                 xp = 0;
  1597.                 netputuev(CONCLASS,CONDATA,myport);
  1598.             } else if ((mycode == CONDATA) && (myport == mytelport)) {
  1599.               connection_status = dumpcon(myport,mywindow);
  1600.             }
  1601.             break;
  1602.  
  1603.         case 21:
  1604. /*
  1605. *  transfer file(s) to the other host via ftp request
  1606. *  file is already open = ftpfh
  1607. */
  1608.             if (mycode == CONDATA) {
  1609.               if (myport == mytelport) {
  1610.                     connection_status = dumpcon(myport,mywindow);
  1611.               } else if (myport == myftpdata) {
  1612.  
  1613.                 netputuev(CONCLASS,CONDATA,myport);        /* Stay alive */
  1614.  
  1615.                 if (towrite <= xp) {
  1616.  
  1617.                     i = BUFFERS;
  1618. #ifdef MACBINARY
  1619.                     towrite = MBread( ftp_mbfp, xs, i);
  1620. #else
  1621. /*                    towrite = read(ftpfh,xs,i);    /*  */
  1622.                     towrite = BUFFERS;
  1623.                     FSRead(ftpfh,&towrite,&xs[0]);
  1624. #endif
  1625.                     xp = 0;
  1626.                 }
  1627.  
  1628.                 if ((towrite <= 0) || netest(myftpdata)) {        /* we are done */
  1629.                     if (ftp_mbfp->fd != 0) MBclose( ftp_mbfp );        /* BYU - close input file */
  1630.                     screens[mywindow].ftpstate = 22;
  1631.                     break;
  1632.                 }
  1633.  
  1634.                 if (ftpfilemode == FAMODE)
  1635.                     i = Sfwrite(myftpdata,&xs[xp],(int) towrite-xp);
  1636.                 else
  1637.                     i = netwrite(myftpdata,&xs[xp],(int) towrite-xp);
  1638.  
  1639.                 if (i > 0) {
  1640.                     xp += i;
  1641.                     translen += i;
  1642.                 }
  1643.  
  1644.                 mytime = TickCount();
  1645.                 if ((transtime + 800) < mytime) {
  1646.                     transtime = mytime;
  1647.                     sprintf(printline,"%ld/%ld bytes sent.\015\013",translen,filelen);
  1648.                     i = strlen(printline);
  1649.                     parse( &screens[mywindow],(unsigned char *) &printline[0],i);
  1650.                 }
  1651.               }
  1652.             }
  1653.  
  1654.             break;
  1655.  
  1656.         case 22:                            /* wait for data to be accepted */
  1657.             netputuev(CONCLASS,CONDATA,myport);        /* Stay alive */
  1658.  
  1659.             fcnt = netpush(myftpdata);        /* will go negative on err */
  1660.             if (!fcnt || netest(myftpdata)) {
  1661.                 mycode = CONCLOSE;
  1662.                 sprintf(printline,"%ld/%ld bytes sent.\015\013",translen,filelen);
  1663.                 parse( &screens[mywindow],(unsigned char *) &printline[0],strlen(printline));
  1664.             }
  1665.             if ((mycode == CONDATA) && (myport == mytelport)) connection_status = dumpcon(myport,mywindow);
  1666.             break;
  1667.  
  1668. /* Get a file from the remote connection */
  1669.         case 30:
  1670.             if (mycode == CONFAIL) mycode = CONCLOSE;    /* something went wrong */
  1671.  
  1672.             if (mycode == CONOPEN) {
  1673.                 screens[mywindow].ftpstate = 31;
  1674.                 filelen = xp = 0;
  1675.                 transtime = TickCount();
  1676.                 translen = 0L;
  1677.             } else if ((mycode == CONDATA) && (myport == mytelport)) {
  1678.               connection_status = dumpcon(myport,mywindow);
  1679.             }
  1680.             break;
  1681.  
  1682. /*
  1683. * file has already been opened, take everything from the connection
  1684. * and place into the open file: ftpfh
  1685. */
  1686.         case 31:
  1687.             if (mycode == CONDATA) {
  1688.               if (myport == mytelport) {
  1689.                     connection_status = dumpcon(myport,mywindow);
  1690.               } else if (myport == myftpdata) {
  1691.  
  1692. /* wait until xs is full before writing to disk */
  1693.                 if (filelen <= 2000) {
  1694.  
  1695.                     if (xp) {
  1696. #ifdef MACBINARY
  1697.                         if (0 > MBwrite(ftp_mbfp, xs, xp))
  1698.                             mycode = CONCLOSE;
  1699. #else
  1700.                         if (0 > write(ftpfh,xs,xp))        /* disk full err */
  1701.                             mycode = CONCLOSE;
  1702. #endif
  1703.                       xp = 0;
  1704.                     }
  1705.                     filelen = BUFFERS;        /* expected or desired len to go */
  1706.                 }
  1707.  
  1708.                 if (mycode == CONDATA) {
  1709.                     if (ftpfilemode == FAMODE)
  1710.                         fcnt = Sfread(myftpdata,&xs[xp],(int)filelen);
  1711.                     else
  1712.                         fcnt = netread(myftpdata,&xs[xp],(int)filelen);
  1713.  
  1714.                     if (fcnt >= 0) {
  1715.                         filelen -= fcnt;
  1716.                         xp += fcnt;
  1717.                         translen += fcnt;
  1718.                     }
  1719.  
  1720.                     mytime = TickCount();
  1721.                     if ((transtime + 800) < mytime) {
  1722.                         transtime = mytime;
  1723.                         if ((screens[mywindow].clientflags & MGET_STATE) == 0) {
  1724.                             sprintf(printline,"%ld bytes received.\015\013",translen);
  1725.                             i = strlen(printline);
  1726.                             parse( &screens[mywindow],(unsigned char *) &printline[0],i);
  1727.                     }    }
  1728.  
  1729. /*                    printf(" %d %d %d \012",filelen,xp,fcnt);
  1730.                     n_row();  
  1731. */
  1732.                     if (fcnt < 0) {
  1733. #ifdef MACBINARY
  1734.                         if (0 > MBwrite( ftp_mbfp, xs, xp)) {
  1735.                             break;
  1736.                         }
  1737.                         if (ftp_mbfp->fd != 0) {
  1738.                             MBclose( ftp_mbfp );
  1739.                         }
  1740. #else
  1741.                         if (0 > write(ftpfh,xs,xp)) { /* disk full check */
  1742.                             break;
  1743.                         }
  1744.                         Close(ftpfh);        /* BYU LSC */
  1745. #endif
  1746.                           ftpfh = 0;
  1747.                     }
  1748.                     netputuev(CONCLASS,CONDATA,myport);
  1749.                 }
  1750.               }
  1751.             }
  1752. /* Ouput any remaining data before closing */
  1753.             if (mycode == CONCLOSE) {
  1754.                 if (xp) {
  1755. #ifdef MACBINARY
  1756.                     if (0 > MBwrite(ftp_mbfp, xs, xp))
  1757.                         netclose(myftpdata);
  1758. #else
  1759.                     if (0 > write(ftpfh,xs,xp))        /* disk full err */
  1760.                         netclose(myftpdata);
  1761. #endif
  1762.                 }
  1763.                 if ((screens[mywindow].clientflags & MGET_STATE) == 0) {
  1764.                     sprintf(printline,"%ld bytes received.\015\013",translen);
  1765.                     i = strlen(printline);
  1766.                     parse( &screens[mywindow],(unsigned char *) &printline[0],i);
  1767.             }    }
  1768.             break;
  1769.  
  1770. /* Waiting for "ftpdata" connection to open, display any communication 
  1771.    from the telnet port. */
  1772.         case 40:
  1773.             if (mycode == CONOPEN) 
  1774.                 screens[mywindow].ftpstate = 41;
  1775.  
  1776.             if ((myport == myftpdata) &&
  1777.                 ((screens[mywindow].clientflags & CAPTURE_DATA) != 0)) {
  1778.                 captcon(myport,mywindow);
  1779.             } else {
  1780.                 connection_status = dumpcon(myport,mywindow);
  1781.             }
  1782.             break;
  1783.  
  1784. /* If the "ftpdata" port is open, then postpone reading and displaying 
  1785.    any data from other ports once data has been received.  Otherwise, 
  1786.    read and display data from anywhere. */
  1787.         case 41:
  1788.             if (mycode == CONDATA) {
  1789.                 if ((myport == myftpdata) &&
  1790.                     ((screens[mywindow].clientflags & CAPTURE_DATA) != 0)) {
  1791.                     captcon(myport,mywindow);
  1792.                 } else {
  1793.                     connection_status = dumpcon(myport,mywindow);
  1794.                 }
  1795.                 if (myport == myftpdata) screens[mywindow].ftpstate = 42;
  1796.                 netputuev(CONCLASS,CONDATA,myport);
  1797.             } else if (mycode == CONCLOSE) {
  1798.                 screens[mywindow].ftpstate = 40;
  1799.             }
  1800.             break;
  1801.  
  1802. /* Only data from "ftpdata" */
  1803.         case 42:
  1804.             if (mycode == CONDATA) {
  1805.                 if (myport == myftpdata) {
  1806.                     if ((screens[mywindow].clientflags & CAPTURE_DATA) != 0) {
  1807.                         captcon(myport,mywindow);
  1808.                     } else {
  1809.                         connection_status = dumpcon(myport,mywindow);
  1810.                 }    }
  1811.                 netputuev(CONCLASS,CONDATA,myport);            /* Keep port monitoring alive */
  1812.             } else if (mycode == CONCLOSE) {
  1813.                 screens[mywindow].ftpstate = 40;
  1814.             }
  1815.             break;
  1816.  
  1817.     }  /* end of switch */
  1818.  
  1819. /*
  1820. *  After reading from connection, if the connection is closed,
  1821. *  reset up shop.
  1822. */
  1823.     if ((mycode == CONCLOSE) || (connection_status < 0)) {        /* BYU 2.4.12 */
  1824.         if (connection_status < 0)                                /* BYU 2.4.12 */
  1825.             screens[mywindow].clientflags &= ~MPUT_STATE;
  1826.         if (ftpfh > 0) {
  1827. /*            Close(ftpfh);        /* BYU LSC */
  1828.             ftpfh = 0;
  1829.         }
  1830.         if (ftp_mbfp->fd != 0) MBclose( ftp_mbfp );
  1831.         screens[mywindow].ftpstate = 1;
  1832.         fcnt = 0;
  1833.         if (myftpdata == myport) {
  1834.             netclose(myftpdata);
  1835.             Sptypes[myftpdata] = -1;
  1836.             screens[mywindow].ftpport = -1;
  1837.         }
  1838.         if ((screens[mywindow].clientflags & TYPE_I_ON_CLOSE) != 0) {
  1839.             screens[mywindow].clientflags = 0;
  1840.             cmd_status = ftpdo(mywindow,"TYPE I","");
  1841.         }
  1842.  
  1843. /* Send the next file of an MPUT */
  1844.         if ((screens[mywindow].clientflags & MPUT_STATE) != 0) {
  1845.             needanswer = TRUE;
  1846.             while (needanswer) {
  1847.                 needanswer = FALSE;
  1848.                 if (glob) {                                /* local wildcard expansion */
  1849.                     newfile = (unsigned char *) nextname();    /* get next name */
  1850.                     if (newfile == NULL) {                /* if no expansions yet */
  1851.                         if (getword((char *) captlist,(char *) transfile)) {
  1852.                             newfile = (unsigned char *) firstname((char *) transfile);    /* get first name */
  1853.                             if (newfile == NULL) {            /* if no expansions */
  1854.                                 sprintf(printline,"No match for %s",transfile);
  1855.                                 nputs(printline);
  1856.                     }    }    }
  1857.                 } else if (getword((char *) captlist,(char *) transfile)) {
  1858.                     newfile = transfile;
  1859.                 } else newfile = NULL;
  1860.  
  1861.                 if (newfile == NULL) {
  1862.                     screens[mywindow].clientflags &= ~MPUT_STATE;
  1863.                     screens[mywindow].ftpstate = 1;
  1864.                 } else {
  1865. #if 1    /* When prompting is fixed switch to the code below */
  1866.                     sprintf(screens[mywindow].ftpbuf,"STOR \"%s\"",newfile);
  1867.                     cmd_status = ftpdo(mywindow,screens[mywindow].ftpbuf,"");
  1868. #else
  1869.                     if (prompt) {                            /* check */
  1870.                         sprintf(printline,"mput %s? ",newfile);
  1871.                         putstring(mywindow,printline);
  1872.                         if (ftpgets(answer,20,1) == ABORT) {    /* abort */
  1873.                             screens[mywindow].clientflags &= ~MPUT_STATE;
  1874.                             screens[mywindow].ftpstate = 1;
  1875.                         } else if (tolower(*(stpblkp(answer))) != 'y') {
  1876.                             needanswer = TRUE;
  1877.                         } else {
  1878.                             sprintf(screens[mywindow].ftpbuf,"STOR \"%s\"",newfile);
  1879.                             cmd_status = ftpdo(mywindow,screens[mywindow].ftpbuf,"");
  1880.                         }
  1881.                     } else {
  1882. /* The Mac file may have special characters, so quote the whole thing */
  1883.                         sprintf(screens[mywindow].ftpbuf,"STOR \"%s\"",newfile);
  1884.                         cmd_status = ftpdo(mywindow,screens[mywindow].ftpbuf,"");
  1885.                     }
  1886. #endif
  1887.          }    }    }
  1888.  
  1889.         if ((screens[mywindow].clientflags & MGET_STATE) != 0) {
  1890.             screens[mywindow].ftpstate = 5;            /* BYU 3 */
  1891.             netputuev(CONCLASS,CONDATA,mytelport);    /* BYU 3 - Stay alive to transfer file */
  1892.         }
  1893.     }
  1894.     return(TRUE);
  1895. }
  1896.  
  1897.  
  1898. #if 0
  1899. /************************************************************************/
  1900. /* getdir: get current directory.  Finds current drive and current path
  1901. * on drive, returns a string.
  1902. *
  1903. /************************************************************************/
  1904.  
  1905. getdir(drive,path) int drive; char *path; {
  1906. char partpath[64];
  1907.  
  1908. if (!drive) drive = getdsk();    /* current disk */
  1909. getcd(drive+1,partpath);    /* current dir */
  1910. sprintf(path,"%c:\\%s",'A'+drive,partpath);
  1911. return(TRUE);
  1912. }
  1913.  
  1914.  
  1915. finduniq(name,list,listsize) char *name, *list[]; int listsize; {
  1916. int i,j=NONE,len;
  1917.  
  1918. len = strlen(name);
  1919. for (i=0; i<listsize; i++) {
  1920.     if (!strncmp(name,list[i],len)) {        /* prefix */
  1921.     if (len==strlen(list[i])) return(i+1);    /* exact match */
  1922.     if (j!=NONE) j = AMBIGUOUS;    /* more than one match */
  1923.     else j = i+1;            /* note prefix found */
  1924.     }
  1925. }
  1926. return(j);            /* prefix */
  1927. }
  1928. #endif
  1929.  
  1930.  
  1931. /***************************************************************************/
  1932. /*  dosescape
  1933. *  escape to dos for processing
  1934. *  put the connections to automated sleep while in DOS
  1935. /************************************************************************/
  1936.  
  1937. dosescape() {
  1938.  
  1939. #if 0
  1940.     int i;
  1941.     nputs("Warning, some programs will interfere with network communication and can");
  1942.     nputs("cause lost connections.  Do not run any network programs from this DOS shell.");
  1943.     nputs("Type 'EXIT' to return to FTP");
  1944. /*
  1945. *  invoke a put-to-sleep routine which calls netsleep every 8/18ths of a sec
  1946. */
  1947.  
  1948.     tinst();
  1949.     i = system("command");        /* call DOS */
  1950.     tdeinst();
  1951.  
  1952.     if (i < 0) {
  1953.         nputs("\012\012Error loading COMMAND.COM");
  1954.         nputs("Make sure COMMAND.COM is specified under COMSPEC.");
  1955.         nputs("It must also be in a directory which is in your PATH statement.");
  1956.     }
  1957.  
  1958. /*    if (fromtty) n_row();    /*  */
  1959. #endif
  1960.     return(0);
  1961. }
  1962.  
  1963. #if 0
  1964. static int scrsetup;
  1965.  
  1966. nputs(line) char *line; {
  1967. if (!scrsetup) {
  1968.     scrsetup = 1;
  1969.     if (fromtty) {
  1970.         n_clear();            /* clear screen */
  1971.         n_wrap(1);            /* cursor positioning */
  1972.         n_cur(0,0);
  1973.         n_color(2);            /* set color to green */
  1974.     }
  1975.  
  1976.     nputs("             National Center for Supercomputing Applications");
  1977.     nputs("                      FTP version 1.04  7/5/88\012");
  1978. }
  1979. if (fromtty) n_puts(line);
  1980. else puts(line);
  1981. return(TRUE);
  1982. }
  1983. #endif